package vn.mahjonggame.game.request;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.log4j.Logger;

import vn.mahjonggame.game.Mahjong;
import vn.mahjonggame.game.MahjongExtension;
import vn.mahjonggame.metadata.GameActionType;
import vn.mahjonggame.metadata.Player;
import vn.mahjonggame.metadata.MObject;
import vn.mahjonggame.metadata.Response;
import vn.mahjonggame.metadata.RoomVarName;
import vn.mahjonggame.metadata.Tile;
import vn.mahjonggame.metadata.TileSet;
import vn.mahjonggame.platform.PlatformConfig;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;

public class CallRiichiHandler extends BaseClientRequestHandler {

	@Override
	public void handleClientRequest(final User user, ISFSObject params) {
		final MahjongExtension ext = (MahjongExtension) getParentExtension();
		Mahjong mahjong = ext.getMahjong();
		Logger logger = mahjong.getLogger();
		
		Room room = ext.getGameRoom();
		List<User> users = room.getUserList();
		
		final Player player = mahjong.getPlayerById(user.getId());
		player.cancelTimer();
		
		
		Tile tile = player.getJustPickedTile();
		
		int bonusTime = params.getInt(MObject.bonusTime.toString());
		
		/*
		 * +1 HAN
		 */
		player.addHanScore(1);
		
		/*
		 * Turn on the RIICHI flag
		 */
		player.setRiichiWaiting(true);
		
		/*
		 * Trace the number of KAN/CHI/PON call
		 */
		Map<Integer, Boolean> numKCPCallDuringRiichiMap = mahjong.getNumKCPCallDuringRiichiMap();
		numKCPCallDuringRiichiMap.put(player.getPlayerId(), false);
				
		Response.Builder object = new Response.Builder();
		object.losePos(player.getPlayerPosition())
				.winPos(player.getPlayerPosition())
				.loseTile(tile.getId());
		
		for(Iterator<User> iUsers = users.iterator(); iUsers.hasNext();){
			User iUser = iUsers.next();
			Response.Builder response = new Response.Builder();			
			
			logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "iUser: " + iUser.toString()));
			
			if(iUser.equals(user)){
				/*
				 * Tenpai on Kokushi musou
				 */
				logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "numKokushiMusou: " + player.getNumKokushiMusou()));
				if(player.getNumKokushiMusou() == 12){
					object.winTile(mahjong.tileArrayToTileIdArray(player.getNonYaochuhaiTiles()));					
				}
				else {
					object.winTile(mahjong.tileArrayToTileIdArray(player.getDiscretedTiles()));					
				}
			}
			else {
				object.winTile(new ArrayList<Integer>());
			}
					
			response.RIICHI(object.build().getSFSObject())
					.turn(player.getPlayerPosition());
			
			SFSObject responseTmp = response.build().getSFSObject();
			logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "response: " + responseTmp.toString()));
			send(GameActionType.callRiichi.toString(), responseTmp, iUser);
		}			
		
		mahjong.getCalledRiichiPlayers().add(player);
		player.setHasThrown(false);		
		ext.addAction(user, GameActionType.callRiichi.toString());
		
		player.updateBonusTime();
		
		logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "Bonus time from client: " + bonusTime * 1000));			
		logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "Bonus time from server: " + player.getBonusTime()));
		logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "startTime: " + player.getStartTime()));
		logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "leftTime: " + (player.getEndTime() - player.getStartTime())));
		
		mahjong.setPlayerInTurn(player);
		
		if(player.isDisconnect() || Boolean.valueOf(room.getVariable(RoomVarName.is_auto.toString()).getStringValue())){
			/*
			 * Wait 5 second. If player does not thrown the tile, auto thrown the tile
			 */		
			
			final Response.Builder nextParams = new Response.Builder();			
			int size = player.getLeftTiles().size();
			tile = player.getLeftTiles().get(size - 1);
			nextParams.tile(tile.getId())
						.bonusTime(player.getBonusTime());			
			
			int delay = player.getTurnTime() + player.getBonusTime();	
			/*
			 * Only wait 1 second if the player is disconnected
			 */
			if(player.isDisconnect()){
				delay = 1000;
			}
			
			logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "isDisconnect: " + player.isDisconnect()));
			logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "isRiichiWaiting: " + player.isRiichiWaiting()));
			logger.info(mahjong.log(room, player, GameActionType.callRiichi.toString(), "Calling throw handler: " + delay));
			
			Timer timer = player.getTimer();
			timer.schedule(new TimerTask() {
				  @Override
				  public void run() {
					  if(!player.isHasThrown()){
						  ThrowTileHandler throwTileHandler = new ThrowTileHandler();					  
						  throwTileHandler.throwTile(ext, user, nextParams.build().getSFSObject(), true, false);
					  }								
				  }
			}, delay);
		}
	}
}